package blaha.genalg.graphgen;

import java.util.Date;
import java.util.Random;

import org.apache.log4j.Logger;

import blaha.genalg.beans.Board;
import blaha.genalg.methods.CountDistance;
import blaha.genalg.methods.ReadAllProperties;
import blaha.genalg.staticmethods.Combination;
import blaha.logging.Log;

/**
 * Joins points on first-level basis
 * 
 * @author pblaha
 * 
 */
public class JoinBasicPoints {

	private static final Logger log = Log.getLoggerMoje();

	/**
	 * Connect choosed points together
	 * 
	 * @param settings
	 * @param board
	 * @return
	 */
	public Board Join(Board board, ReadAllProperties settings) {
		// join points...how much joins?I take a middle from every point
		// max-min*count
		// Integer joins = settings.getConnectionsOnBoard();
		float flowDistance = settings.minDistance;
		int unSuccesfulljoins = 0;

		// no more connections than maximum possible
		if (settings.connectionsOnBoard > Combination.comb(board.getPoints(), 2))
			settings.connectionsOnBoard = Combination.comb(board.getPoints(), 2);
		
		Random rand = new Random(new Date().getTime());
		
		/**
		 * int cyclicDefender=0, cyclicCounter = 0;
		 */
		boolean warn=false;
		for (int i = 0; i < settings.connectionsOnBoard;) {
			/**
			 * Protection against infinite loop cyclicDefender check if "I"
			 * changed, cyclicCounter counts solutionless loops
			 */
			// if(cyclicCounter==200)
			// i++;
			// if(cyclicDefender!=i){
			// cyclicDefender=i;
			// cyclicCounter=0;
			// }
			// else
			// cyclicCounter++;

			
			if(flowDistance>settings.maxDistance&&!warn){
				warn=true;
				log.warn("Maximum distance is overstepped, consider alow more joins");
			}
			
			/**
			 * If distance is too small for points
			 */
			if (unSuccesfulljoins >= settings.attemptToJoinPoints) {
				unSuccesfulljoins = 0;
				flowDistance+=settings.DistanceStep;

				//log.debug("Flow Distance increased, new value=" + flowDistance);
			}

			// choose two not-same points
			boolean test;
			int p1, p2;
			do {
				p1 = rand.nextInt(board.getPoints());
				p2 = rand.nextInt(board.getPoints());
				// loop protection
				// if(p1==0)
				// p1++;
				// half matrix, p1 conn p2 is the same as p2 conn p1
				
				// no more connections with this point, if limit exceeded
				// exists..no more same connections
				// check if distance is ok, set distance and weight
			test=((board.getAllConnectionsOfNodeFromMatrixOfJoins(p1) > settings.maxConnections || board.getAllConnectionsOfNodeFromMatrixOfJoins(p2) > settings.maxConnections)||(Board.matrixOfJoins[p1][p2].isConnected()));
			} while ((p1 <= p2)||test);


			
			if (CountDistance.betweenTwoPoints(Board.map.get(p1), Board.map.get(p2)) < (flowDistance)) {
				Board.matrixOfJoins[p1][p2].setConnected(true);
				Board.matrixOfJoins[p1][p2].setDistance(CountDistance.betweenTwoPoints(Board.map.get(p1), Board.map.get(p2)));
				Board.matrixOfJoins[p1][p2].setWeigth(Board.matrixOfJoins[p1][p2].getDistance() * rand.nextFloat());
				i++;
				flowDistance = settings.minDistance;
				//log.debug("Next join created=" + i + " ,count=" + settings.getConnectionsOnBoard());
				continue;
			} else
				unSuccesfulljoins++;
		}

		return board;
	}
}
